package com.zh.modules.app.utils;

import com.google.common.hash.Hashing;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;

import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class StringUtil extends StringUtils {
    private static final Logger log = LoggerFactory.getLogger(StringUtil.class);

    public static String showShort(String content, int length, String mark) {
        if (content == null) {
            return null;
        }
        if (content.getBytes().length <= length) {
            return content;
        }
        byte[] s = content.getBytes();
        int flag = 0;
        for (int i = 0; i < length; i++) {
            if (s[i] < 0) {
                flag++;
            }
        }
        if (flag % 2 != 0) {
            length--;
        }
        byte[] d = new byte[length];
        System.arraycopy(s, 0, d, 0, length);
        return new String(d) + mark;
    }

    public static String showShort(String content, int length) {
        return showShort(content, length, "..");
    }

    public static String encodeBase64(String str) {
        if (str == null) {
            return null;
        }
        return Base64.getEncoder().encodeToString(str.getBytes());
    }

    public static String decodeBase64(String str) {
        if (str == null) {
            return null;
        }
        return new String(Base64.getDecoder().decode(str.getBytes()));
    }

    public static String getMd5(String str) {
        if ((str == null) || (str.length() == 0)) {
            return "";
        }
        return Hashing.md5().newHasher().putString(str, StandardCharsets.UTF_8).hash().toString();
    }

    public static String get16Md5(String plainText) {
        return getMd5(plainText).substring(8, 24);
    }

    public static String decodeQuotedPrintable(String str) {
        byte escapeChar = 61;
        if (str == null) {
            return null;
        }
        byte[] bytes = str.getBytes();
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        for (int i = 0; i < bytes.length; i++) {
            int b = bytes[i];
            if (b == escapeChar) {
                try {
                    int u = Character.digit((char) bytes[(++i)], 16);
                    int l = Character.digit((char) bytes[(++i)], 16);
                    if ((u == -1) || (l == -1)) {
                        return "";
                    }
                    buffer.write((char) ((u << 4) + l));
                } catch (ArrayIndexOutOfBoundsException e) {
                    return "";
                }
            }
            buffer.write(b);
        }
        bytes = buffer.toByteArray();
        return new String(bytes, StandardCharsets.UTF_8);
    }

    public static boolean endsWithIgnoreCase(String beChecked, String str) {
        if ((beChecked == null) || (str == null)) {
            return false;
        }
        return beChecked.toUpperCase().endsWith(str.toUpperCase());
    }

    public static String findStr(String source, String start, String end) {
        if (source == null) {
            return null;
        }
        if (!isEmpty(start)) {
            int i = source.indexOf(start);
            if (i < 0) {
                return null;
            }
            source = source.substring(i + start.length());
        }
        if (!isEmpty(end)) {
            int i = source.indexOf(end);
            if (i < 0) {
                return null;
            }
            source = source.substring(0, i);
        }
        return source;
    }

    public static StringBuilder appendBuilder(StringBuilder sb, CharSequence... strs) {
        for (CharSequence str : strs) {
            sb.append(str);
        }
        return sb;
    }

    public static String removeSuffix(CharSequence str, CharSequence suffix) {
        if (isEmpty(str)) {
            return StringPool.EMPTY;
        }

        if (isEmpty(suffix)) {
            return str.toString();
        }

        final String str2 = str.toString();
        if (str2.endsWith(suffix.toString())) {
            return subPre(str2, str2.length() - suffix.length());
        }
        return str2;
    }

    public static String subPre(CharSequence string, int toIndex) {
        return sub(string, 0, toIndex);
    }

    public static String sub(CharSequence str, int fromIndex, int toIndex) {
        if (isEmpty(str)) {
            return StringPool.EMPTY;
        }
        int len = str.length();

        if (fromIndex < 0) {
            fromIndex = len + fromIndex;
            if (fromIndex < 0) {
                fromIndex = 0;
            }
        } else if (fromIndex > len) {
            fromIndex = len;
        }

        if (toIndex < 0) {
            toIndex = len + toIndex;
            if (toIndex < 0) {
                toIndex = len;
            }
        } else if (toIndex > len) {
            toIndex = len;
        }

        if (toIndex < fromIndex) {
            int tmp = fromIndex;
            fromIndex = toIndex;
            toIndex = tmp;
        }

        if (fromIndex == toIndex) {
            return StringPool.EMPTY;
        }

        return str.toString().substring(fromIndex, toIndex);
    }

    public static String humpToUnderline(String para) {
        para = lowerFirst(para);
        StringBuilder sb = new StringBuilder(para);
        int temp = 0;

        for (int i = 0; i < para.length(); ++i) {
            if (Character.isUpperCase(para.charAt(i))) {
                sb.insert(i + temp, "_");
                ++temp;
            }
        }

        return sb.toString().toLowerCase();
    }

    public static String lowerFirst(String str) {
        char firstChar = str.charAt(0);
        if (firstChar >= 'A' && firstChar <= 'Z') {
            char[] arr = str.toCharArray();
            arr[0] = (char) (arr[0] + 32);
            return new String(arr);
        } else {
            return str;
        }
    }

    public static String cleanIdentifier(@Nullable String param) {
        if (param == null) {
            return null;
        } else {
            StringBuilder paramBuilder = new StringBuilder();

            for (int i = 0; i < param.length(); ++i) {
                char c = param.charAt(i);
                if (Character.isJavaIdentifierPart(c)) {
                    paramBuilder.append(c);
                }
            }

            return paramBuilder.toString();
        }
    }
}
